﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using LLClient.ClientServiceRef;
using LLClient.ServerProxy;

namespace LLClient.Battle
{
    /// <summary>
    /// Interaction logic for PlacementShipWindow.xaml
    /// </summary>
    public partial class PlacementShipWindow : Window
    {
        #region Constant Values
        private const int N_LINES = 10;
        private const int BLOCK_SIZE = 30;
        private const int FIELD_SIZE = 50;
        private const int PATROL = 1;
        private const int SUBMARINE = 2;
        private const int DESTROYER = 3;
        private const int BATTLESHIP = 4;
        private const int CARRIER = 5;
        #endregion

        int selectedShip = 0;
        int selectedStartIndex = 0;
        int shipSize = 0;
        bool isDrawing = false;
        private bool[] placed;
        UserControl ucShip;

        //Ships to be placed
        ShipPatrolControl shipPatrol;
        ShipSubmarineControl shipSubmarine;
        ShipDestroyerControl shipDestroyer;
        ShipBattleshipControl shipBattleship;
        ShipCarrierControl shipCarrier;

        List<bool> battleField;
        private Dictionary<int, int> ships;
        private bool isReady = false;

        private Proxy _proxy = Proxy.GetInstance();
        private bool _eventRegistered = false;
        private Client _currentClient = Proxy.GetInstance().CurrentClient;

        public Client CurrentClient
        {
            get { return _currentClient; }
            set { _currentClient = value; }
        }

        public PlacementShipWindow()
        {
            InitializeComponent();
            DrawLinesInMap();

            shipPatrol = new ShipPatrolControl();
            shipSubmarine = new ShipSubmarineControl();
            shipDestroyer = new ShipDestroyerControl();
            shipBattleship = new ShipBattleshipControl();
            shipCarrier = new ShipCarrierControl();

            ships = new Dictionary<int, int>();
            battleField = new List<bool>();
            for (int i = 0; i < 100; i++)
                battleField.Add(false);
            placed = new bool[5];
            finishButton.IsEnabled = false;
            readyButton.IsEnabled = false;

            if (!_eventRegistered)
            {
                if (_proxy != null)
                    _proxy.ProxyCallbackEvent += _proxy_ProxyCallbackEvent;

                _eventRegistered = true;
            }
            this.Closing += new System.ComponentModel.CancelEventHandler(PlacementShipWindow_Closing);
        }

        void PlacementShipWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (_proxy != null)
                _proxy.ProxyCallbackEvent -= _proxy_ProxyCallbackEvent;
            _eventRegistered = false;
        }

        void _proxy_ProxyCallbackEvent(object sender, ProxyCallbackEventArgs e)
        {
            Dispatcher.BeginInvoke(new Action(() =>
            {
                if (e.Sender != null)
                {
                    switch (e.CallbackType)
                    {
                        case CallbackType.PlacementDone:
                            MessageBox.Show("Your enemy," + e.Sender.Username + ", has finished setting their fleet!", CurrentClient.Username + ": Information", MessageBoxButton.OK, MessageBoxImage.Information);
                            break;
                        case CallbackType.PlayerReady:
                            if(!isReady)
                                MessageBox.Show("Your enemy, " + e.Sender.Username + ", is ready to fight..", CurrentClient.Username + ": Information", MessageBoxButton.OK, MessageBoxImage.Information);
                            break;
                        case CallbackType.GameStarted:
                            //if (e.Message.Respond)
                            //{
                            //    MessageBox.Show("You will move first!", CurrentClient.Username + ": Information", MessageBoxButton.OK, MessageBoxImage.Information);
                            //}
                            //else
                            //{
                            //    MessageBox.Show("Your enemy will move first!", CurrentClient.Username + ": Information", MessageBoxButton.OK, MessageBoxImage.Information);
                            //}
                            BattleWindow bWindow = new BattleWindow(e.Message.Respond, grid2, ships);
                            bWindow.Show();
                            this.Close();
                            break;
                    }
                }
            }));
        }

        private void DrawLinesInMap()
        {
            // draw vertical lines
            for (int i = 1; i < N_LINES; i++)
            {
                Line line = new Line();

                line.Stroke = Brushes.Black;
                line.Fill = Brushes.Black;
                line.StrokeThickness = 1;
                line.X1 = i * BLOCK_SIZE;
                line.X2 = line.X1;

                line.Y1 = 0;
                line.Y2 = grid2.Height;

                grid2.Children.Add(line);
            }

            // draw horizontal lines
            for (int i = 1; i < N_LINES; i++)
            {
                Line line = new Line();

                line.Stroke = Brushes.Black;
                line.Fill = Brushes.Black;
                line.StrokeThickness = 1;
                line.Y1 = i * BLOCK_SIZE;
                line.Y2 = line.Y1;

                line.X1 = 0;
                line.X2 = grid2.Width;

                grid2.Children.Add(line);
            }
        }
        
        private void grid2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (isDrawing)
            {
                if (isPositionValid())
                {
                    Point p = e.GetPosition(this.grid2);
                    ucShip.Margin = new Thickness(((int)(p.X / 30)) * 30, ((int)(p.Y / 30)) * 30, 0, 0);

                    for (int i = selectedStartIndex; i < selectedStartIndex + shipSize; i++)
                    {
                        battleField[i] = true;
                        ships.Add(i, selectedShip);
                    }

                    switch (selectedShip)
                    {
                        case PATROL:
                            patrolButton.IsEnabled = false;
                            break;
                        case SUBMARINE:
                            submarineButton.IsEnabled = false;
                            break;
                        case DESTROYER:
                            destroyerButton.IsEnabled = false;
                            break;
                        case BATTLESHIP:
                            battleshipButton.IsEnabled = false;
                            break;
                        case CARRIER:
                            carrierButton.IsEnabled = false;
                            break;
                    }

                    ucShip = null;
                    isDrawing = false;

                    placed[selectedShip - 1] = true;
                    bool isAllPlaced = true;
                    for (int i = 0; i < 5; i++)
                        if (!placed[i])
                            isAllPlaced = false;
                    if (isAllPlaced)
                    {
                        finishButton.IsEnabled = true;
                    }
                }
                else
                {
                    MessageBox.Show("Position is not valid", CurrentClient.Username + ": Warning", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
            
        }

        private void grid2_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDrawing)
            {
                if (grid2.Children.IndexOf(ucShip) > 0)
                    grid2.Children.Remove(ucShip);

                Point p = e.GetPosition(this.grid2);
                selectedStartIndex = ((int)p.Y / 30 * 10) + (int)p.X / 30;

                ucShip.Margin = new Thickness(((int)(p.X / 30)) * 30, ((int)(p.Y / 30)) * 30, 0, 0);
                grid2.Children.Add(ucShip);
            }
            
        }

        private void shipButton_Click(object sender, RoutedEventArgs e)
        {
            Button senderButton = (Button)sender;

            if (senderButton.Equals(patrolButton))
            {
                selectedShip = PATROL;
                ucShip = shipPatrol;
                shipSize = 2;
            }
            else if (sender.Equals(submarineButton))
            {
                selectedShip = SUBMARINE;
                ucShip = shipSubmarine;
                shipSize = 3;
            }
            else if (sender.Equals(destroyerButton))
            {
                selectedShip = DESTROYER;
                ucShip = shipDestroyer;
                shipSize = 3;
            }
            else if (sender.Equals(battleshipButton))
            {
                selectedShip = BATTLESHIP;
                ucShip = shipBattleship;
                shipSize = 4;
            }
            else if (sender.Equals(carrierButton))
            {
                selectedShip = CARRIER;
                ucShip = shipCarrier;
                shipSize = 5;
            }

            if (!isDrawing)
            {
                isDrawing = true;
            }
            else
            {

            }
        }

        private void grid2_MouseLeave(object sender, MouseEventArgs e)
        {
            if (isDrawing)
            {
                if (grid2.Children.IndexOf(ucShip) > 0)
                    grid2.Children.Remove(ucShip);
            }
            else
            {

            }
        }

        private void finishButton_Click(object sender, RoutedEventArgs e)
        {
            ClientServiceRef.Grid gridBattle = new ClientServiceRef.Grid();
            gridBattle.Ships = ships;
            try
            {
                _proxy.ProxyService.ConfirmShipsPlacement(CurrentClient, gridBattle);
                readyButton.IsEnabled = true;
                resetButton.IsEnabled = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, CurrentClient.Username + ": Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void resetButton_Click(object sender, RoutedEventArgs e)
        {
            _resetAll();
        }

        private void readyButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                _proxy.ProxyService.ReadyForBattle();
                isReady = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, CurrentClient.Username + ": Error", MessageBoxButton.OK, MessageBoxImage.Error);
                isReady = false;
            }
        }

        private bool isPositionValid()
        {
            if ((selectedStartIndex % 10) + shipSize > 10)
                return false;

            for (int i = selectedStartIndex; i < selectedStartIndex + shipSize; i++)
                if (battleField[i])
                    return false;

            return true;
        }

        private void _resetAll()
        {
            ships = new Dictionary<int, int>();
            battleField = new List<bool>();
            for (int i = 0; i < 100; i++)
                battleField.Add(false);
            placed = new bool[5];
            finishButton.IsEnabled = false;
            readyButton.IsEnabled = false;

            // reset buttons
            if (grid2.Children.Contains(shipPatrol))
            {
                grid2.Children.Remove(shipPatrol);
                patrolButton.IsEnabled = true;
            }
            if (grid2.Children.Contains(shipDestroyer))
            {
                grid2.Children.Remove(shipDestroyer);
                destroyerButton.IsEnabled = true;
            }
            if (grid2.Children.Contains(shipSubmarine))
            {
                grid2.Children.Remove(shipSubmarine);
                submarineButton.IsEnabled = true;
            }
            if (grid2.Children.Contains(shipBattleship))
            {
                grid2.Children.Remove(shipBattleship);
                battleshipButton.IsEnabled = true;
            }
            if (grid2.Children.Contains(shipCarrier))
            {
                grid2.Children.Remove(shipCarrier);
                carrierButton.IsEnabled = true;
            }
        }

    }
}
